package com.utilmodule;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by aya4 on 2015/12/15.
 */
public class BitmapUtil {
	public final static String TAG = "BitmapUtil";
	/** 图片最大宽度. */
	public static final int MAX_WIDTH = 4096 / 2;

	/** 图片最大高度. */
	public static final int MAX_HEIGHT = 4096 / 2;

	/**
	 * 圆角图片
	 * 
	 * @param bitmap
	 * @param pixels
	 * @return
	 */
	public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		int color = 0xff424242;
		Paint paint = new Paint();
		Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		RectF rectF = new RectF(rect);
		float roundPx = pixels;
		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);
		canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);
		if (bitmap != null && !bitmap.isRecycled()) {
			bitmap.recycle();
		}
		return output;
	}

	/**
	 * 圆形图片
	 *
	 * @param bitmap
	 * @return
	 */
	public static Bitmap toRoundBitmap(Bitmap bitmap) {

		if (bitmap == null) {
			return null;
		}
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		float roundPx;
		float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
		if (width <= height) {
			roundPx = width / 2;
			top = 0;
			bottom = width;
			left = 0;
			right = width;
			height = width;
			dst_left = 0;
			dst_top = 0;
			dst_right = width;
			dst_bottom = width;
		} else {
			roundPx = height / 2;
			float clip = (width - height) / 2;
			left = clip;
			right = width - clip;
			top = 0;
			bottom = height;
			width = height;
			dst_left = 0;
			dst_top = 0;
			dst_right = height;
			dst_bottom = height;
		}
		Bitmap output = Bitmap.createBitmap(width, height,
				Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		final int color = 0xff424242;
		final Paint paint = new Paint();
		final Rect src = new Rect((int) left, (int) top, (int) right,
				(int) bottom);
		final Rect dst = new Rect((int) dst_left, (int) dst_top,
				(int) dst_right, (int) dst_bottom);
		final RectF rectF = new RectF(dst);
		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);
		canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
		canvas.drawBitmap(bitmap, src, dst, paint);
		if (bitmap != null && !bitmap.isRecycled()) {
			bitmap.recycle();
			bitmap = null;
		}
		return output;
	}

	/**
	 * 缩放图片
	 *
	 * @param bm
	 *            要缩放图片
	 * @param newWidth
	 *            宽度
	 * @param newHeight
	 *            高度
	 * @return处理后的图片
	 */
	public static Bitmap scaleImage(Bitmap bm, int newWidth, int newHeight) {
		if (bm == null) {
			return null;
		}
		int width = bm.getWidth();
		int height = bm.getHeight();
		float scaleWidth = ((float) newWidth) / width;
		float scaleHeight = ((float) newHeight) / height;
		Matrix matrix = new Matrix();
		matrix.postScale(scaleWidth, scaleHeight);
		Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,
				true);
		if (bm != null & !bm.isRecycled()) {
			bm.recycle();// 销毁原图片
			bm = null;
		}
		return newbm;
	}

	/**
	 * 旋转图片
	 *
	 * @param angle
	 *            旋转角度
	 * @param bitmap
	 *            要处理的Bitmap
	 * @return 处理后的Bitmap
	 */
	public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
		// 旋转图片 动作
		Matrix matrix = new Matrix();
		matrix.postRotate(angle);
		// 创建新的图片
		Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
				bitmap.getWidth(), bitmap.getHeight(), matrix, true);
		if (resizedBitmap != bitmap && bitmap != null && !bitmap.isRecycled()) {
			bitmap.recycle();
			bitmap = null;
		}
		return resizedBitmap;
	}

	/**
	 * 描述：裁剪图片.
	 *
	 * @param file
	 *            File对象
	 * @param desiredWidth
	 *            新图片的宽
	 * @param desiredHeight
	 *            新图片的高
	 * @return Bitmap 新图片
	 */
	public static Bitmap getCutBitmap(File file, int desiredWidth,
			int desiredHeight) {

		Bitmap resizeBmp = null;

		BitmapFactory.Options opts = new BitmapFactory.Options();
		// 设置为true,decodeFile先不创建内存 只获取一些解码边界信息即图片大小信息
		opts.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(file.getPath(), opts);

		// 获取图片的原始宽度
		int srcWidth = opts.outWidth;
		// 获取图片原始高度
		int srcHeight = opts.outHeight;

		int[] size = resizeToMaxSize(srcWidth, srcHeight, desiredWidth,
				desiredHeight);
		desiredWidth = size[0];
		desiredHeight = size[1];

		// 默认为ARGB_8888.
		opts.inPreferredConfig = Config.RGB_565;
		// 以下两个字段需一起使用：
		// 产生的位图将得到像素空间，如果系统gc，那么将被清空。当像素再次被访问，如果Bitmap已经decode，那么将被自动重新解码
		opts.inPurgeable = true;
		// 位图可以共享一个参考输入数据(inputstream、阵列等)
		opts.inInputShareable = true;
		// 缩放的比例，缩放是很难按准备的比例进行缩放的，通过inSampleSize来进行缩放，其值表明缩放的倍数，SDK中建议其值是2的指数值
		int sampleSize = findBestSampleSize(srcWidth, srcHeight, desiredWidth,
				desiredHeight);
		opts.inSampleSize = sampleSize;
		// 创建内存
		opts.inJustDecodeBounds = false;
		// 使图片不抖动
		opts.inDither = false;
		resizeBmp = BitmapFactory.decodeFile(file.getPath(), opts);

		if (resizeBmp != null) {
			resizeBmp = getCutBitmap(resizeBmp, desiredWidth, desiredHeight);
		}
		return resizeBmp;
	}

	public static Bitmap getCutBitmap(FileDescriptor fd, int desiredWidth,
			int desiredHeight) {

		Bitmap resizeBmp = null;

		BitmapFactory.Options opts = new BitmapFactory.Options();
		// 设置为true,decodeFile先不创建内存 只获取一些解码边界信息即图片大小信息
		opts.inJustDecodeBounds = true;
		// BitmapFactory.decodeFile(file.getPath(), opts);

		BitmapFactory.decodeFileDescriptor(fd, null, opts);
		// 获取图片的原始宽度
		int srcWidth = opts.outWidth;
		// 获取图片原始高度
		int srcHeight = opts.outHeight;

		int[] size = resizeToMaxSize(srcWidth, srcHeight, desiredWidth,
				desiredHeight);
		desiredWidth = size[0];
		desiredHeight = size[1];

		// 默认为ARGB_8888.
		opts.inPreferredConfig = Config.RGB_565;
		// 以下两个字段需一起使用：
		// 产生的位图将得到像素空间，如果系统gc，那么将被清空。当像素再次被访问，如果Bitmap已经decode，那么将被自动重新解码
		opts.inPurgeable = true;
		// 位图可以共享一个参考输入数据(inputstream、阵列等)
		opts.inInputShareable = true;
		// 缩放的比例，缩放是很难按准备的比例进行缩放的，通过inSampleSize来进行缩放，其值表明缩放的倍数，SDK中建议其值是2的指数值
		int sampleSize = findBestSampleSize(srcWidth, srcHeight, desiredWidth,
				desiredHeight);
		opts.inSampleSize = sampleSize;
		// 创建内存
		opts.inJustDecodeBounds = false;
		// 使图片不抖动
		opts.inDither = false;
		resizeBmp = BitmapFactory.decodeFileDescriptor(fd, null, opts);

		if (resizeBmp != null) {
			resizeBmp = getCutBitmap(resizeBmp, desiredWidth, desiredHeight);
		}
		return resizeBmp;
	}

	/**
	 * 描述：裁剪图片.
	 *
	 * @param
	 *
	 * @param desiredWidth
	 *            新图片的宽
	 * @param desiredHeight
	 *            新图片的高
	 * @return Bitmap 新图片
	 */
	public static Bitmap getCutBitmap(Context context, int resId,
			int desiredWidth, int desiredHeight) {

		Bitmap resizeBmp = null;

		BitmapFactory.Options opts = new BitmapFactory.Options();
		// 设置为true,decodeFile先不创建内存 只获取一些解码边界信息即图片大小信息
		opts.inJustDecodeBounds = true;

		BitmapFactory.decodeResource(context.getResources(), resId, opts);
		// BitmapFactory.decodeFile(file.getPath(), opts);

		// 获取图片的原始宽度
		int srcWidth = opts.outWidth;
		// 获取图片原始高度
		int srcHeight = opts.outHeight;

		int[] size = resizeToMaxSize(srcWidth, srcHeight, desiredWidth,
				desiredHeight);
		desiredWidth = size[0];
		desiredHeight = size[1];

		// 默认为ARGB_8888.
		opts.inPreferredConfig = Config.RGB_565;
		// 以下两个字段需一起使用：
		// 产生的位图将得到像素空间，如果系统gc，那么将被清空。当像素再次被访问，如果Bitmap已经decode，那么将被自动重新解码
		opts.inPurgeable = true;
		// 位图可以共享一个参考输入数据(inputstream、阵列等)
		opts.inInputShareable = true;
		// 缩放的比例，缩放是很难按准备的比例进行缩放的，通过inSampleSize来进行缩放，其值表明缩放的倍数，SDK中建议其值是2的指数值
		int sampleSize = findBestSampleSize(srcWidth, srcHeight, desiredWidth,
				desiredHeight);
		opts.inSampleSize = sampleSize;
		// 创建内存
		opts.inJustDecodeBounds = false;
		// 使图片不抖动
		opts.inDither = false;
		resizeBmp = BitmapFactory.decodeResource(context.getResources(), resId,
				opts);

		if (resizeBmp != null) {
			resizeBmp = getCutBitmap(resizeBmp, desiredWidth, desiredHeight);
		}
		return resizeBmp;
	}

	/**
	 * 描述：裁剪图片.
	 *
	 * @param bitmap
	 *            the bitmap
	 * @param desiredWidth
	 *            新图片的宽
	 * @param desiredHeight
	 *            新图片的高
	 * @return Bitmap 新图片
	 */
	public static Bitmap getCutBitmap(Bitmap bitmap, int desiredWidth,
			int desiredHeight) {

		if (!checkBitmap(bitmap)) {
			return null;
		}

		if (!checkSize(desiredWidth, desiredHeight)) {
			return null;
		}

		Bitmap resizeBmp = null;

		try {
			int width = bitmap.getWidth();
			int height = bitmap.getHeight();

			int offsetX = 0;
			int offsetY = 0;

			if (width > desiredWidth) {
				offsetX = (width - desiredWidth) / 2;
			} else {
				desiredWidth = width;
			}

			if (height > desiredHeight) {
				offsetY = (height - desiredHeight) / 2;
			} else {
				desiredHeight = height;
			}

			resizeBmp = Bitmap.createBitmap(bitmap, offsetX, offsetY,
					desiredWidth, desiredHeight);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (resizeBmp != bitmap) {
				bitmap.recycle();
			}
		}
		return resizeBmp;
	}

	/**
	 * 找到最合适的SampleSize
	 *
	 * @param width
	 * @param height
	 * @param desiredWidth
	 * @param desiredHeight
	 * @return
	 */
	private static int findBestSampleSize(int width, int height,
			int desiredWidth, int desiredHeight) {
		double wr = (double) width / desiredWidth;
		double hr = (double) height / desiredHeight;
		double ratio = Math.min(wr, hr);
		float n = 1.0f;
		while ((n * 2) <= ratio) {
			n *= 2;
		}
		return (int) n;
	}

	private static int[] resizeToMaxSize(int srcWidth, int srcHeight,
			int desiredWidth, int desiredHeight) {
		int[] size = new int[2];
		if (desiredWidth <= 0) {
			desiredWidth = srcWidth;
		}
		if (desiredHeight <= 0) {
			desiredHeight = srcHeight;
		}
		if (desiredWidth > MAX_WIDTH) {
			// 重新计算大小
			desiredWidth = MAX_WIDTH;
			float scaleWidth = (float) desiredWidth / srcWidth;
			desiredHeight = (int) (desiredHeight * scaleWidth);
		}

		if (desiredHeight > MAX_HEIGHT) {
			// 重新计算大小
			desiredHeight = MAX_HEIGHT;
			float scaleHeight = (float) desiredHeight / srcHeight;
			desiredWidth = (int) (desiredWidth * scaleHeight);
		}
		size[0] = desiredWidth;
		size[1] = desiredHeight;
		return size;
	}

	private static boolean checkBitmap(Bitmap bitmap) {
		if (bitmap == null) {
			Log.e(TAG, "原图Bitmap为空了");
			return false;
		}

		if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
			Log.e(TAG, "原图Bitmap大小为0");
			return false;
		}
		return true;
	}

	private static boolean checkSize(int desiredWidth, int desiredHeight) {
		if (desiredWidth <= 0 || desiredHeight <= 0) {
			Log.e(TAG, "请求Bitmap的宽高参数必须大于0");
			return false;
		}
		return true;
	}

	/**
	 * 图片保存到本地
	 *
	 * */
	public static String saveBitmap(Context context,Bitmap bitmap, String bitName)
			throws IOException

	{
		String path = "";
		if (context.getExternalCacheDir() == null) {
			path = context.getFilesDir().getPath();
		} else {
			path = context.getExternalCacheDir().getPath();
		}

		String Newpath = path + "/" + "Imager" + "/" + bitName;
		File file = new File(Newpath);
		if (file.exists()) {
			file.delete();
		}
		FileOutputStream out;
		try {
			out = new FileOutputStream(file);
			if (bitmap.compress(CompressFormat.JPEG, 100, out)) {
				out.flush();
				out.close();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return Newpath;
	}

	/**
	 * 图片保存到本地
	 *
	 * */
	public static void saveMyBitmap(Context context,String bitName, Bitmap mBitmap) {
		String path = "";
		if (context.getExternalCacheDir() == null) {
			path = context.getFilesDir().getPath();
		} else {
			path = context.getExternalCacheDir().getPath();
		}
		File f = new File(path + "/" + "Imager" + "/" + bitName
				+ ".jpg");
		try {
			f.createNewFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
		}
		FileOutputStream fOut = null;
		try {
			fOut = new FileOutputStream(f);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		mBitmap.compress(CompressFormat.JPEG, 30, fOut);
		try {
			fOut.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			fOut.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 图片的质量压缩
	 * */
	public static Bitmap compressImage(Bitmap image) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		image.compress(CompressFormat.JPEG, 50, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
		int options = 90;
		int longs = baos.toByteArray().length;
		while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
			baos.reset();// 重置baos即清空baos
			image.compress(CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
			longs = baos.toByteArray().length;
			options -= 10;// 每次都减少10
		}
		ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
		Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
		return bitmap;
	}

	/**
	 * @Description: TODO(图片的像素压缩)
	 * @author renbo
	 * @date 2017-1-3 上午10:59:03
	 * @version V1.0
	 */
	public static Bitmap getimage(String srcPath) {
		BitmapFactory.Options newOpts = new BitmapFactory.Options();
		// 开始读入图片，此时把options.inJustDecodeBounds 设回true了
		newOpts.inJustDecodeBounds = true;
		Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空

		newOpts.inJustDecodeBounds = false;
		int w = newOpts.outWidth;
		int h = newOpts.outHeight;
		// 现在主流手机比较多是800*480分辨率，所以高和宽我们设置为
		float hh = 800f;// 这里设置高度为800f
		float ww = 480f;// 这里设置宽度为480f
		// 缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
		int be = 1;// be=1表示不缩放
		if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
			be = (int) (newOpts.outWidth / ww);
		} else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
			be = (int) (newOpts.outHeight / hh);
		}
		if (be <= 0)
			be = 1;
		newOpts.inSampleSize = be;// 设置缩放比例
		// 重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
		bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
		return bitmap;
	}

	/**
	 * @param file
	 *            目标文件
	 * @param bitmap
	 * @param size
	 *            ：目标文件大小,单位k
	 * @return
	 * @title:图片压缩处理
	 * @author: YangHongyuan
	 * @date: 2015年1月6日
	 */
	public static boolean doCompress(File file, Bitmap bitmap, int size) {
		boolean flag = false;
		try {
			if (file.exists()) {
				file.delete();
			}
			file.createNewFile();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			String fileType = file.getName()
					.substring(file.getName().indexOf(".")).toLowerCase();
			if (".jpg".equals(fileType) || ".jpeg".equals(fileType)) {
				baos = doCompress(bitmap, 800, 1024, size);
				// png无法压缩
			} else if (".png".equals(fileType)) {
				flag = bitmap.compress(CompressFormat.PNG, 100, baos);
			}

			FileOutputStream outStream = new FileOutputStream(file);

			baos.writeTo(outStream);

			outStream.flush();
			outStream.close();
		} catch (Exception ex) {
			ex.printStackTrace();
			Log.i("savaImager", ex + "bo=============>>>>>>>>>>");
		}

		return flag;
	}

	/**
	 * @param maxW
	 *            最大宽度
	 * @param maxH
	 *            最大高度
	 * @param bitmap
	 * @param size
	 *            ：目标文件大小,单位k
	 * @return
	 * @title:图片压缩处理
	 * @author: YangHongyuan
	 * @date: 2015年1月6日
	 */
	private static ByteArrayOutputStream doCompress(Bitmap bitmap, int maxW,
			int maxH, int size) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bitmap = resize(bitmap, maxW, maxH);
		// size <=0，不压缩
		if (size <= 0) {
			size = 10000;
		}

		// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
		int quality = 100;
		bitmap.compress(CompressFormat.JPEG, quality, baos);
		while (baos.size() / 1024f > size) {
			quality = quality - 5;// 每次都减少5
			baos.reset();// 清空stream
			if (quality <= 0) {
				break;
			}
			bitmap.compress(CompressFormat.JPEG, quality, baos);
		}

		return baos;
	}

	/**
	 * @param bitmap
	 * @param maxW
	 * @param maxH
	 * @return
	 * @title: 重设图片大小
	 * @author: YangHongyuan
	 * @date: 2015年4月21日
	 */
	public static Bitmap resize(Bitmap bitmap, int maxW, int maxH) {
		// 获取这个图片的宽和高
		float width = bitmap.getWidth();
		float height = bitmap.getHeight();

		// 创建操作图片用的matrix对象
		Matrix matrix = new Matrix();

		// 计算宽高缩放率
		float scaleWidth = ((float) maxW) / width;
		float scaleHeight = ((float) maxH) / height;
		float scale = scaleWidth;
		if (scale > scaleHeight) {
			scale = scaleHeight;
		}
		if (scale < 1) {
			// 缩放图片动作
			matrix.postScale(scale, scale);
			bitmap = Bitmap.createBitmap(bitmap, 0, 0, (int) width,
					(int) height, matrix, true);
		}
		return bitmap;
	}
}
